/*
 * Copyright (c) 2022. China Mobile (SuZhou) Software Technology Co.,Ltd. All rights reserved.
 * Lakehouse is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package com.chinamobile.cmss.lakehouse.common.engine;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class EngineLauncher<T extends CommandBuilder> {

    protected T builder;
    ProcessBuilder.Redirect outputStream;
    ProcessBuilder.Redirect errorStream;
    boolean redirectErrorStream;

    public EngineLauncher(T builder) {
        this.builder = builder;
    }

    protected abstract String findSubmitShell() throws Exception;

    List<String> getArgs() {
        return builder.buildSubmitArgs();
    }

    public void setExtraEnv(Map<String, String> env) {
        this.builder.childEnv().putAll(env);
    }

    public Process launcher() {
        try {
            List<String> cmd = new ArrayList<>();
            cmd.add(findSubmitShell());
            cmd.addAll(getArgs());
            ProcessBuilder builder = createBuilder(cmd);
            Process childProc = builder.start();
            return childProc;
        } catch (Exception e) {
            log.error("Failed to launcher app: ", e);
            return null;
        }
    }

    public Process launcher(File logFile) {
        try {
            List<String> cmd = new ArrayList<>();
            cmd.add(findSubmitShell());
            cmd.addAll(getArgs());
            ProcessBuilder builder = createBuilder(cmd);
            builder.redirectError(logFile);
            builder.redirectOutput(logFile);
            Process childProc = builder.start();
            return childProc;
        } catch (Exception e) {
            log.error("Failed to launcher app: ", e);
            return null;
        }
    }

    protected ProcessBuilder createBuilder(List<String> cmd) {
        Iterator var3;

        log.info("Run command: {}", cmd);
        ProcessBuilder pb = new ProcessBuilder(cmd);
        var3 = builder.childEnv().entrySet().iterator();

        while (var3.hasNext()) {
            Map.Entry<String, String> e = (Map.Entry) var3.next();
            pb.environment().put(e.getKey(), e.getValue());
        }

        if (redirectErrorStream) {
            pb.redirectErrorStream(true);
        }
        if (errorStream != null) {
            pb.redirectError(errorStream);
        }
        if (outputStream != null) {
            pb.redirectOutput(outputStream);
        }

        return pb;
    }
}
